import 'dart:ffi';

import 'dart:io';
import 'dart:isolate';

import 'package:ffi/ffi.dart';
import 'package:flutter_track/base/base_logger.dart';
import 'package:flutter_track/utils/file_save_utils.dart';

/// 无值返回
typedef CVoidFunctionVoidParams = Void Function();
typedef DartVoidFunctionVoidParams = void Function();

/// 具备int传入值的
typedef CVoidFunctionIntParams = Void Function(Int64, Int64);
typedef DartVoidFunctionIntParams = void Function(int, int);

/// 具备传入 string 值的
typedef CVoidfunctionStringParams = Void Function(Pointer<Utf8>);
typedef DartVoidFunctionStringParams = void Function(Pointer<Utf8>);

/// 返回指针类型的内容
typedef CVoidFunctionVoidParamsPointer = Pointer<Void> Function();
typedef DartVoidFunctionVoidParamsPointer = Pointer<Void> Function();

const String registerSignalCallback = "registerSignalListenInMainIsolate";
const String releaseCppTracker = "releaseTracker";
const String trackerDoTrack = "sendTrackSignal";
const String trackerDoTrackWithBaseIsolate =
    "sendTrackSignalWithBaseIsolateInstructions";
const String setTrackerTraceSavePath = "setTrackStackSavePath";

const String tag = "TrackerWorkerFFI";

class TrackerWorkerFFI {
  static void doCppTrack(
    int baseIsolate,
    int baseVm,
  ) {
    var func = _ensureLinkLib()
        .lookup<NativeFunction<CVoidFunctionIntParams>>(
          trackerDoTrackWithBaseIsolate,
        )
        .asFunction<DartVoidFunctionIntParams>();
    func.call(baseIsolate, baseVm);

    Log.printAndroidLogger("tracker do track, baseIsolate: $baseIsolate");
  }

  /// 释放ffi
  static void releaseFFI() {
    DartVoidFunctionVoidParams? dartFunc = _ensureLinkLib()
        .lookup<NativeFunction<CVoidFunctionVoidParams>>(
          releaseCppTracker,
        )
        .asFunction<DartVoidFunctionVoidParams>();
    dartFunc.call();
  }

  /// 注册信号监听，只能在mainisolate中
  static void registerSignalToMainIsolate() {
    if (Isolate.current.debugName == 'main') {
      Log.info(tag: tag, message: "register on main isolate...");
      DartVoidFunctionVoidParams? dartFunc = _ensureLinkLib()
          .lookup<NativeFunction<CVoidFunctionVoidParams>>(
            registerSignalCallback,
          )
          .asFunction<DartVoidFunctionVoidParams>();
      dartFunc.call();
    } else {
      Log.info(
          tag: tag,
          message: "should registe signal on main isolate...... error......");
    }
  }

  /// 设置文件存储路径
  static Future<void> setStackSaveSavePath({String? savePath}) async {
    String actualSavePath = "";
    if (savePath == null || savePath.isEmpty) {
      actualSavePath = await FileSaveUtils.getFileSavePath();
    } else {
      actualSavePath = savePath;
    }

    /// call ffi function set save path....
    DartVoidFunctionStringParams func = _ensureLinkLib()
        .lookup<NativeFunction<CVoidfunctionStringParams>>(
          setTrackerTraceSavePath,
        )
        .asFunction<DartVoidFunctionStringParams>();
    Pointer<Utf8> stringPointer = actualSavePath.toNativeUtf8();
    func.call(stringPointer);
    malloc.free(stringPointer);
  }

  static DynamicLibrary _ensureLinkLib() {
    DynamicLibrary trackLib;
    if (Platform.isAndroid) {
      trackLib = DynamicLibrary.open("libtracker-lib.so");
    } else if (Platform.isIOS) {
      trackLib = DynamicLibrary.process();
    } else {
      throw UnsupportedError("unknown platform...");
    }
    return trackLib;
  }
}
